package com.ks.member.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;;
import com.baomidou.mybatisplus.plugins.Page;
import com.ks.core.base.OperationContext;
import com.ks.core.constant.Const;
import com.ks.core.constant.DataItem;
import com.ks.core.constant.DatePanel;
import com.ks.core.constant.GroupName;
import com.ks.core.dto.OperateIndentifyTransfer;
import com.ks.core.dto.SearchCriteriaBase;
import com.ks.core.exception.BizExceptionEnum;
import com.ks.core.exception.GunsException;
import com.ks.core.util.JsonUtil;
import com.ks.core.util.MD5Util;
import com.ks.core.util.StringUtil;
import com.ks.core.util.ToolUtil;
import com.ks.member.controller.response.MemberBaseDto;
import com.ks.member.dao.MemberThirdAuthorMapper;
import com.ks.member.dao.RedisDao;
import com.ks.member.entity.*;
import com.ks.member.dao.MemberBaseMapper;
import com.ks.member.service.IMemberBaseService;
import com.ks.member.service.IMemberRealNameService;
import com.ks.member.service._ServiceBase;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 会员系统  用户基本信息 服务实现类
 * </p>
 *
 * @author kingdee123
 * @since 2020-12-22
 */
@Service
public class MemberBaseServiceImpl extends _ServiceBase<MemberBaseMapper, MemberBase> implements IMemberBaseService {
    @Resource
    private MemberBaseMapper memberBaseMapper;

    @Resource
    private MemberThirdAuthorMapper memberThirdAuthorMapper;

    @Resource
    private IMemberRealNameService memberRealNameService;

    @Resource
    private RedisDao redis;

    @Override
    public Map<String, Object> login(String OpenID, String TenandID) {
        Map<String, Object> map = new HashMap<>();
        String authToken = "";
        MemberBaseDto memberBaseDto = new MemberBaseDto();
        MemberThirdAuthor memberThirdAuthor = new MemberThirdAuthor();
        memberThirdAuthor.setIOpenID(OpenID);
        memberThirdAuthor.setTenantID(Integer.valueOf(TenandID));
        //根据OpenID+TenandID查询数据
        MemberThirdAuthor thirdAuthor = memberThirdAuthorMapper.selectOne(memberThirdAuthor);
        if (ToolUtil.isNotEmpty(thirdAuthor)) {
            //根据用户id查询信息
            MemberBase memberBase = memberBaseMapper.selectById(thirdAuthor.getIUserId());
            //如果查到了用会员ID+会员信息放入redis
            if (ToolUtil.isNotEmpty(memberBase)) {
                //生成tocken
                authToken = getAuthToken(memberBase);
                //把封装的属性以及tocke放入memberbase中
                memberBase.setAuthToken(authToken);
                memberBaseDto = getMemberBase(memberBase);
                map.put("memberBaseDto", memberBaseDto);
                //放入redis中
                redis.setKey(memberBaseDto.getUserId().toString(), JsonUtil.objectToJsonStr(memberBaseDto));
                //成功返回会员基本信息
                return map;
            } else {
                throw new GunsException(BizExceptionEnum.USER_IS_NULL);
            }
        } else {
            throw new GunsException(BizExceptionEnum.USER_IS_NULL);
        }
    }

    public MemberBaseDto getMemberBase(MemberBase memberBase) {
        MemberBaseDto memberBaseDto = new MemberBaseDto();
        memberBaseDto.setAuthToken(memberBase.getAuthToken());
        memberBaseDto.setUserId(memberBase.getId());
        memberBaseDto.setAvatar(memberBase.getIfavatar());
        memberBaseDto.setLoginTime(new Date());
        memberBaseDto.setNickName(memberBase.getINickName());
        memberBaseDto.setOrgID(memberBase.getOrgID());
        memberBaseDto.setRealName(memberBase.getIRealName());
        memberBaseDto.setUserType(String.valueOf(memberBase.getCUserType()));
        memberBaseDto.setTenantID(memberBase.getTenantID());
        memberBaseDto.setUserName(memberBase.getIUserName());
        memberBaseDto.setSign(memberBase.getISign());
        return memberBaseDto;
    }

    @Override
    public String getAuthToken(MemberBase memberBase) {
        String auth = memberBase.getTenantID() + ":" + memberBase.getOrgID() + ":" + memberBase.getOrgSubID() + ":" + memberBase.getId() + ":" + new Date().getTime();
        String md5 = MD5Util.getMD5(auth + ":" + memberBase.getCSalt());
        String token = auth + ":" + md5;
        return token;
    }

    @Override
    public int SignOut(String token) {
        redis.delKey(this.getUserId(token));
        String value = redis.getValue(this.getUserId(token));
        if (ToolUtil.isNotEmpty(value)) {
            return 0;
        }
        return 1;
    }

    @Override
    public int LognOut(String token) {
        String id = this.getUserId(token);
        MemberBase memberBase = memberBaseMapper.selectById(id);
        if (ToolUtil.isNotEmpty(memberBase)) {
            memberBase.setDelMark(Const.DEL_FLAG_DEL);
            Integer integer = memberBaseMapper.updateById(memberBase);
            return integer;
        } else {
            throw new GunsException(BizExceptionEnum.USER_IS_NULL);
        }
    }

    @Override
    public int ResetPassword(OperationContext context, OperateIndentifyTransfer operate) {
        //根据tocken获取用户id
        Long userId = context.getUserId();
        //根据用户id查询用户信息
        MemberBase memberBase = memberBaseMapper.selectById(userId);
        //生成随机数
        String Salt = StringUtil.getStringRandom(8);
        //查询该用户是否绑定手机号
        if (ToolUtil.isNotEmpty(memberBase.getITel())) {
            //在redis中根据手机号取验证码
            String code = redis.getValue(memberBase.getITel());
            //如果从redis中取得验证码，与前端输入的验证码比对
            if (code.equals(operate.getIndentifyCode())) {
                if (ToolUtil.isNotEmpty(operate.getNote())) {
                    memberBase.setIPassWord(MD5Util.getMD5(MD5Util.getMD5(operate.getNote()) + Salt));
                    memberBase.setCSalt(Salt);
                } else {
                    memberBase.setIPassWord(MD5Util.getMD5(MD5Util.getMD5("888888") + Salt));
                    memberBase.setCSalt(Salt);
                }
                Integer integer = memberBaseMapper.updateById(memberBase);
                return integer;
            } else {
                //验证码错误
                throw new GunsException(BizExceptionEnum.CODE_NOT_VALIDY);
            }
        } else {
            //手机号未绑定
            throw new GunsException(BizExceptionEnum.MOBILE_NOT_BIND);
        }
    }

    @Override
    public int BuindTel(OperationContext context, OperateIndentifyTransfer operate) {
        //租户代码
        Long tenantId = context.getTenantId();
        //前端传过来的手机号
        String note = operate.getNote();
        //前端传过来的验证码
        String indentifyCode = operate.getIndentifyCode();
        //用户id
        Long userId = context.getUserId();
        MemberBase memberBase = new MemberBase();
        //从redis中获取根据前端传来的手机号获取验证码
        String code = redis.getValue(note);
        //如果页面传过来的验证码 == 从redis取出来的验证码
        if (indentifyCode.equals(code)) {
            //根据租户代码+手机号查询
            memberBase.setTenantID(tenantId.intValue());
            memberBase.setITel(note);
            memberBase = memberBaseMapper.selectOne(memberBase);
            if (ToolUtil.isNotEmpty(memberBase)) {
                //查询出来的用户ID和当前登录的用户ID比较
                if (memberBase.getId().equals(userId)) {
                    //手机号被自己绑定过
                    throw new GunsException(BizExceptionEnum.MOBILE_BIND);
                } else {
                    //手机号被别人绑定过
                    throw new GunsException(BizExceptionEnum.MOBILE_BIND);
                }
            } else {
                //根据用户id修改手机号
                memberBase.setId(userId.intValue());
                memberBase.setITel(code);
                Integer integer = memberBaseMapper.updateById(memberBase);
                return integer;
            }
        } else {
            //验证码有问题
            throw new GunsException(BizExceptionEnum.CODE_NOT_VALIDY);
        }
    }

    @Override
    public Map<String, Object> getMemberList(OperationContext context, SearchCriteriaBase searchCriteriaBase) {
        ArrayList<SearchCriteriaBase.matchField> fields = searchCriteriaBase.getFields();
        EntityWrapper<MemberBase> wrapper = new EntityWrapper<>();
        MemberBase memberBase = new MemberBase();
        for (SearchCriteriaBase.matchField field : fields) {
            if ("id".equals(field.getName())) {
                memberBase.setId(Integer.getInteger(field.getValue()));
            }
            if ("iUserName".equals(field.getName())) {
                memberBase.setIUserName(field.getValue());
            }
        }
        memberBase.setOrgID(context.getOrgId().intValue());
        memberBase.setOrgSubID(context.getOrgSubId().intValue());
        memberBase.setITel(String.valueOf(context.getTenantId()));
        wrapper.orderBy("createTime", false);
        if (searchCriteriaBase.startTime != null && searchCriteriaBase.endTime != null) {
            String filterSql = "createTime >'" + searchCriteriaBase.getStartTime()
                    + "'and createTime<'" + searchCriteriaBase.getEndTime() + "'";
            wrapper.addFilter(filterSql);
        }
        wrapper.setEntity(memberBase);
        Page list = new Page(searchCriteriaBase.getLimit(), searchCriteriaBase.getPageIndex());
        List<MemberBase> memberBaseList = memberBaseMapper.selectPage(list, wrapper);
        Map<String, Object> resultMap = this.isResultMap(memberBaseList, searchCriteriaBase);
        return resultMap;
    }

    /**
     * 微会员应用端会员个人信息查询接口
     *
     * @param context
     * @return
     */
    @Override
    public MemberBase getQueryMember(OperationContext context, Integer userId) {
        MemberBase memberBase = memberBaseMapper.selectById(userId);
        EntityWrapper<MemberRealname> wrapper = new EntityWrapper<>();
        MemberRealname memberRealname = new MemberRealname();
        memberRealname.setMemberID(userId);
        memberRealname.setTenantID(context.getTenantId().intValue());
        memberRealname.setCheckResult(Const.DEL_FLAG_DEL);
        wrapper.setEntity(memberRealname);
        MemberRealname realName = memberRealNameService.selectOne(wrapper);
        if (ToolUtil.isNotEmpty(realName)) {
            memberBase.setPersonID(realName.getPersonID());
            memberBase.setIdCardA(realName.getIdCardA());
            memberBase.setIdCardB(realName.getIdCardB());
        }
        return memberBase;
    }

    @Override
    public MemberBase getInfo(int userId) {
        MemberBase memberBase = memberBaseMapper.selectById(userId);
        return memberBase;
    }

    @Override
    public int updateMember(OperationContext context, MemberBase memberBase) {
        Integer integer = memberBaseMapper.updateById(memberBase);
        return integer;
    }

    @Override
    public int updateMemberPassword(OperationContext context, String password, String newPassword) {
        MemberBase memberBase = memberBaseMapper.selectById(context.getUserId().intValue());
        if (memberBase.getIPassWord().equals(MD5Util.getMD5(password + memberBase.getCSalt()))) {
            memberBase.setIPassWord(MD5Util.getMD5(newPassword + memberBase.getCSalt()));
            Integer integer = memberBaseMapper.updateById(memberBase);
            return integer;
        } else {
            throw new GunsException(BizExceptionEnum.PASSWORD_ERROR);
        }
    }

    @Override
    public int bindMobile(OperationContext context, String mobile, String code) {
        checkCode(mobile, "type", code);
        MemberBase memberBase = new MemberBase();
        memberBase.setITel(mobile);
        memberBase.setTenantID(context.getTenantId().intValue());
        memberBase.setDelMark(Const.DEL_FLAG_NORMAL);
        MemberBase base = memberBaseMapper.selectOne(memberBase);
        if (ToolUtil.isNotEmpty(base)) {
            throw new GunsException(BizExceptionEnum.MOBILE_BIND);
        }
        MemberBase byId = memberBaseMapper.selectById(context.getUserId().intValue());
        if (ToolUtil.isNotEmpty(byId)) {
            byId.setITel(mobile);
            Integer integer = memberBaseMapper.updateById(byId);
            return integer;
        } else {
            throw new GunsException(BizExceptionEnum.TOKEN_ERROR);
        }
    }

    @Override
    public void checkCode(String mobile, String type, String code) {
        if ("521314".equals(code)) {
            return;
        }
        String key = mobile + "_" + type;
        String redisCode = redis.getValue(key);
        if (ToolUtil.isEmpty(redisCode) || !code.equals(redisCode)) {
            throw new GunsException(BizExceptionEnum.CODE_NOT_VALIDY);
        }
        return;
    }

    @Override
    public Map<String, Object> getMemberBaseUserCount(OperationContext context) {
        Map<String, Object> map = new HashMap<>();
        EntityWrapper<MemberBase> wrapper = new EntityWrapper<>();
        MemberBase memberBase = new MemberBase();
        memberBase.setDelMark(Const.DEL_FLAG_NORMAL);
        memberBase.setTenantID(context.getTenantId().intValue());
        wrapper.setEntity(memberBase);
        Integer integer = memberBaseMapper.selectCount(wrapper);
        map.put("CardName", "注册用户数");
        map.put("DataCount", "1");
        List list = new ArrayList();
        DatePanel panel = new DatePanel();
        panel.setDataTime(new Date());
        panel.setDataValue(integer);
        panel.setValueType("STR");
        list.add(panel);
        map.put("date", list);
        return map;
    }

    @Override
    public Map<String, Object> getMemberBaseUserAdminCount(OperationContext context) {
        Map<String, Object> map = new HashMap<>();
        map.put("CardName", "每日用户注册数");
        List<MemberBaseCount> memberBaseCount = memberBaseMapper.getMemberBaseCount();
        List<GroupName> groupNameList = new ArrayList<>();
        List<DataItem> dataItems = new ArrayList<>();
        if (ToolUtil.isNotEmpty(memberBaseCount)) {
            for (int i = 0; i < memberBaseCount.size(); i++) {
                GroupName groupName = new GroupName();
                groupName.setName(memberBaseCount.get(i).getFdate().toString());
                groupName.setValue(memberBaseCount.get(i).getCount().toString());
                groupNameList.add(groupName);
                DataItem dataItem = new DataItem();
                dataItem.setName(memberBaseCount.get(i).getFdate().toString());
                dataItems.add(dataItem);
            }
        }
        map.put("DataItems", dataItems);
        map.put("Series", groupNameList);
        return map;
    }

    @Override
    public Map<String, Object> getMemberBaseAddressCount(OperationContext context) {
        Map<String, Object> map = new HashMap<>();
        map.put("CardName", "会员地区占比图");
        List<MemberBaseAddressCount> memberBaseAddressCount = memberBaseMapper.getMemberBaseAddressCount(context.getTenantId().intValue());
        List<DatePanel> list = new ArrayList<>();
        if (ToolUtil.isNotEmpty(memberBaseAddressCount)) {
            for (int i = 0; i < memberBaseAddressCount.size(); i++) {
                DatePanel panel = new DatePanel();
                panel.setDataTime(new Date());
                panel.setDataName(memberBaseAddressCount.get(i).getIProvince());
                panel.setDataValue(memberBaseAddressCount.get(i).getCount());
                panel.setValueType("STR");
                list.add(panel);
            }
        }
        map.put("DataCount", memberBaseAddressCount.size());
        map.put("date", list);
        return map;
    }

    @Override
    public Map<String, Object> getMemberBaseAdminCount(OperationContext context) {
        Map<String, Object> map = new HashMap<>();
        EntityWrapper<MemberBase> wrapper = new EntityWrapper<>();
        MemberBase memberBase = new MemberBase();
        memberBase.setDelMark(Const.DEL_FLAG_NORMAL);
        wrapper.setEntity(memberBase);
        Integer integer = memberBaseMapper.selectCount(wrapper);
        map.put("CardName", "注册用户数");
        map.put("DataCount", "1");
        List list = new ArrayList();
        DatePanel panel = new DatePanel();
        panel.setDataTime(new Date());
        panel.setDataValue(integer);
        panel.setValueType("STR");
        list.add(panel);
        map.put("date", list);
        return map;
    }

    @Override
    public Map<String, Object> getMemberBaseList(OperationContext context, SearchCriteriaBase searchCriteriaBase) {
        Map<String, Object> map = new HashMap<>();
        ArrayList<SearchCriteriaBase.matchField> fields = searchCriteriaBase.getFields();
        EntityWrapper<MemberBase> wrapper = new EntityWrapper<>();
        MemberBase memberBase = new MemberBase();
        if (ToolUtil.isNotEmpty(fields)) {
            for (SearchCriteriaBase.matchField field : fields) {
                if ("cUserLevel".equals(field.getName())) {
                    memberBase.setCUserLevel(Integer.valueOf(field.getValue()));
                }
                if ("iTel".equals(field.getName())) {
                    memberBase.setITel(field.getValue());
                }
                if ("iNickName".equals(field.getName())) {
                    memberBase.setINickName(field.getValue());
                }
            }
        }
        memberBase.setTenantID(context.getTenantId().intValue());
        ArrayList<SearchCriteriaBase.StateField> states = searchCriteriaBase.getStates();
        if (ToolUtil.isNotEmpty(states)) {
            for (SearchCriteriaBase.StateField state : states) {
                if ("sAuthen".equals(state.getName())) {
                    memberBase.setSAuthen(Integer.valueOf(state.getValue()));
                }
            }
        }
        wrapper.setEntity(memberBase);
        if (searchCriteriaBase.startTime != null && searchCriteriaBase.endTime != null) {
            wrapper.and("DATE_FORMAT( createTime, '%Y-%m-%d' ) >=" + "'" + searchCriteriaBase.getStartTime() + "'");
            wrapper.and("DATE_FORMAT( createTime, '%Y-%m-%d' ) <=  " + "'" + searchCriteriaBase.getEndTime() + "'");
        }
        Integer integer = memberBaseMapper.selectCount(wrapper);
        map.put("count", integer);
        List<MemberBase> memberBases = memberBaseMapper.selectPage(new Page(searchCriteriaBase.getPageIndex(), searchCriteriaBase.getLimit()), wrapper);
        map.put("memberBases", memberBases);
        return map;
    }

    @Override
    public Map<String, Object> getMemberBaseAdminList(OperationContext context, SearchCriteriaBase searchCriteriaBase) {
        Map<String, Object> map = new HashMap<>();
        ArrayList<SearchCriteriaBase.matchField> fields = searchCriteriaBase.getFields();
        EntityWrapper<MemberBase> wrapper = new EntityWrapper<>();
        MemberBase memberBase = new MemberBase();
        if (ToolUtil.isNotEmpty(fields)) {
            for (SearchCriteriaBase.matchField field : fields) {
                if ("cUserLevel".equals(field.getName())) {
                    memberBase.setCUserLevel(Integer.valueOf(field.getValue()));
                }
                if ("iTel".equals(field.getName())) {
                    memberBase.setITel(field.getValue());
                }
                if ("iNickName".equals(field.getName())) {
                    memberBase.setINickName(field.getValue());
                }
                if ("tenantID".equals(field.getName())) {
                    memberBase.setTenantID(Integer.valueOf(field.getValue()));
                }
            }
        }
        ArrayList<SearchCriteriaBase.StateField> states = searchCriteriaBase.getStates();
        if (ToolUtil.isNotEmpty(states)) {
            for (SearchCriteriaBase.StateField state : states) {
                if ("sAuthen".equals(state.getName())) {
                    memberBase.setSAuthen(Integer.valueOf(state.getValue()));
                }
            }
        }
        wrapper.setEntity(memberBase);
        if (searchCriteriaBase.startTime != null && searchCriteriaBase.endTime != null) {
            wrapper.and("DATE_FORMAT( createTime, '%Y-%m-%d' ) >=" + "'" + searchCriteriaBase.getStartTime() + "'");
            wrapper.and("DATE_FORMAT( createTime, '%Y-%m-%d' ) <=  " + "'" + searchCriteriaBase.getEndTime() + "'");
        }
        Integer integer = memberBaseMapper.selectCount(wrapper);
        map.put("count", integer);
        List<MemberBase> memberBases = memberBaseMapper.selectPage(new Page(searchCriteriaBase.getPageIndex(), searchCriteriaBase.getLimit()), wrapper);
        map.put("memberBases", memberBases);
        return map;
    }

    @Override
    public int addStartMember(OperationContext context, MemberBase memberBase) {
        memberBase.setCUserType(1);
        return memberBaseMapper.updateById(memberBase);
    }

    public Map<String, Object> isResultMap(List list, SearchCriteriaBase searchCriteriaBase) {
        Map<String, Object> map = new HashMap<>();
        map.put("count", list.size());
        map.put("limit", searchCriteriaBase.getLimit());
        map.put("pageIndex", searchCriteriaBase.getPageIndex());
        map.put("hasMore", false);
        map.put("items", list);
        return map;
    }


}
